package gossip;

import lombok.Getter;

import java.net.InetSocketAddress;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

public class MembershipTable {

    private final Map<String, MemberState> members = new ConcurrentHashMap<>();
    @Getter
    private MemberState localState;

    public MembershipTable(int port) {
        this.localState = new MemberState("node-" + port, new InetSocketAddress("localhost", port));
    }

    public void merge(MemberState remote) {
        members.compute(remote.getNodeId(), (id, local) -> {
            if (local == null) {
                return remote; // 新节点
            }

            // 使用向量时钟解决冲突
            if (remote.getHeartbeat() > local.getHeartbeat()) {
                return remote; // 采用新状态
            } else if (remote.getHeartbeat() == local.getHeartbeat()) {
                // 相同版本号，合并元数据
                Map<String, String> merged = new HashMap<>(local.getMetadata());
                merged.putAll(remote.getMetadata());
                local.setMetadata(merged);
            }
            return local; // 保留本地状态
        });
    }

    public void incrementLocalHeartbeat() {
        localState.incrementHeartbeat();
    }

    public void updateLocalMetadata(String key, String value) {
        localState.getMetadata().put(key, value);
        incrementLocalHeartbeat();
    }

    public Map<String, MemberState> getMembers() {
        Map<String, MemberState> all = new HashMap<>(members);
        all.put(localState.getNodeId(), localState);
        return Collections.unmodifiableMap(all);
    }

    public List<MemberState> selectRandomTargets(int count) {
        List<MemberState> candidates = new ArrayList<>(getMembers().values());
        candidates.remove(localState); // 排除自身

        Collections.shuffle(candidates);
        return candidates.stream().limit(count).collect(Collectors.toList());
    }
}
